package com.yswee.framework.model;

import java.lang.ref.WeakReference;
import java.net.HttpURLConnection;
import java.util.HashMap;

import com.yswee.framework.Application;
import com.yswee.framework.data.parser.IParser;
import com.yswee.framework.net.ITask;
import com.yswee.framework.net.ITaskContext;
import com.yswee.framework.net.http.Callback;
import com.yswee.framework.net.http.Entity;
import com.yswee.framework.net.http.HttpFactory;
import com.yswee.framework.net.http.HttpType;
import com.yswee.framework.net.http.PostType;

import android.text.TextUtils;

public abstract class BaseModel<T> {

	private IParser<T> mParser;
	private WeakReference<ITaskContext> mContext;
	
	public final IParser<T> getParser() {
		if(mParser == null) {
			mParser = createParser();
		}
		return mParser;
	}
	
	protected ITaskContext getContext() {
		if(mContext != null) {
			return mContext.get();
		}
		return null;
	}
	
	public BaseModel() {
		
	}
	
	public BaseModel(ITaskContext context) {
		mContext = new WeakReference<ITaskContext>(context);
	}
	
	protected abstract IParser<T> createParser();
	
	protected void postData(CharSequence url, HashMap<String, Object> param, Callback<T> c) {
		postData(url, param, getParser(), c);
	}
	
	protected void postData(CharSequence url, HashMap<String, Object> param, Callback<T> c, String debug) {
		postData(url, param, getParser(), c, debug);
	}
	
	protected void postData(CharSequence url, HashMap<String, Object> param, CallbackProxy<T> c) {
		postData(url, param, getParser(), c);
	}
	
	protected <D> void postData(CharSequence url, HashMap<String, Object> param, IParser<D> parser, Callback<D> c) {
		postData(url, param, parser, c, null);
	}
	
	protected <D> void postData(CharSequence url, HashMap<String, Object> param, IParser<D> parser, Callback<D> c, final String debug) {
		CallbackProxy<D> callback = new CallbackProxy<D>(c) {
			protected String getDebugJson() {
				return debug;
			};
		};
		postData(url, param, parser, callback);
	}
	
	protected <D> void postData(CharSequence url, HashMap<String, Object> param, IParser<D> parser, CallbackProxy<D> callback) {
		Entity<D> entity = new Entity<D>();
		entity.setContext(getContext());
		entity.setBaseUrl(getWrapUrlPost(url.toString()));
		entity.setHttpType(HttpType.Post);
		entity.setPostData(getWrapPostData(param));
		entity.setPostType(PostType.TEXT);
		entity.setParser(parser);
		ITask task = HttpFactory.get().createHttp(entity, callback);
		task.excute();
	}
	
	protected void getData(CharSequence url, Callback<T> c) {
		getData(url, getParser(), c, null);
	}
	
	protected void getData(CharSequence url, Callback<T> c, String debug) {
		getData(url, getParser(), c, debug);
	}
	
	protected void getData(CharSequence url, CallbackProxy<T> c) {
		getData(url, getParser(), c);
	}
	
	protected <D> void getData(CharSequence url, IParser<D> parser, Callback<D> c) {
		getData(url, parser, c, null);
	}
	
	protected <D> void getData(CharSequence url, IParser<D> parser, Callback<D> c, final String debug) {
		CallbackProxy<D> callback = new CallbackProxy<D>(c) {
			@Override
			protected String getDebugJson() {
				return debug;
			}
		};
		getData(url, parser, callback);
	}
	
	protected <D> void getData(CharSequence url, IParser<D> parser, CallbackProxy<D> callback) {
		Entity<D> entity = new Entity<D>();
		entity.setContext(getContext());
		entity.setBaseUrl(getWrapUrlGet(url.toString()));
		entity.setHttpType(HttpType.Get);
		entity.setParser(parser);
		ITask task = HttpFactory.get().createHttp(entity, callback);
		task.excute();
	}
	
	protected String getWrapUrlGet(String url) {
		return url;
	}
	
	protected String getWrapUrlPost(String url) {
		return url;
	}
	
	protected HashMap<String, Object> getWrapPostData(HashMap<String, Object> param) {
		return param;
	}
	
	public static class CallbackProxy<T> extends Callback<T> {
		
		protected Callback<T> mCallback;
		
		public CallbackProxy(Callback<T> callback) {
			mCallback = callback;
		}
		
		@Override
		public T onProcessData(Entity<T> entity, String result) {
			if (mCallback != null) {
				return mCallback.onProcessData(entity, result);
			} else {
				return super.onProcessData(entity, result);
			}
		}

		@Override
		public void onFinish(Entity<T> entity) {
			if(mCallback != null)
				mCallback.onFinish(entity);
		}

		@Override
		public void onError(Entity<T> entity) {
			if(Application.get().getAppConfigure().getIsDebug()) {
				String json = getDebugJson();
				if(!TextUtils.isEmpty(json)) {
					entity.setParsedData(onProcessData(entity, json));
					onFinish(entity);
					return;
				}
			}
			if(mCallback != null)
				mCallback.onError(entity);
		}

		@Override
		public void onCancel(Entity<T> entity) { 
			if(mCallback != null)
				mCallback.onCancel(entity);
		}
		
		@Override
		public void onInvalid(Entity<T> entity) { 
			if(mCallback != null)
				mCallback.onInvalid(entity);
		}

		@Override
		public void onBeginResponse(HttpURLConnection connection) { 
			if(mCallback != null)
				mCallback.onBeginResponse(connection);
		}

		@Override
		public void onEndResponse(Entity<T> entity) {
			if(mCallback != null)
				mCallback.onEndResponse(entity);
		}

		@Override
		public void onBeginRequest(Entity<T> entity) {
			if(mCallback != null)
				mCallback.onBeginRequest(entity);
		}
		
		@Override
		public void onBeginConnection(HttpURLConnection connection) { 
			if(mCallback != null)
				mCallback.onBeginConnection(connection);
		}

		@Override
		public void onDownloadProgress(Entity<T> entity) {
			if(mCallback != null)
				mCallback.onDownloadProgress(entity);
		}
		
		protected String getDebugJson() {
			return null;
		}
		
	}

}
